﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using UnityEngine;

namespace ZSW.Framework
{
    public class ZSWF_Ini
    {
        /// <summary>
        /// 通过内容解析配置文件
        /// </summary>
        /// <param name="content">内容</param>
        public static Dictionary<string, ZSWF_IniSection> ParseIni(string content)
        {
            var sections = new Dictionary<string, ZSWF_IniSection>();
            ZSWF_IniSection currentSection = null;
            using (StringReader stringReader = new StringReader(content))
            {
                string line;
                while ((line = stringReader.ReadLine()) != null)
                {
                    line = line.Trim();
                    //Comment
                    if (line.StartsWith(";")) continue;
                    //Section
                    if (line.StartsWith("[") && line.EndsWith("]"))
                    {
                        var sectionName = line.TrimStart('[').TrimEnd(']').Trim();
                        currentSection = new ZSWF_IniSection(sectionName);
                        sections.Add(currentSection.Title, currentSection);
                        continue;
                    }
                    //Key=Id
                    if (line.Contains("="))
                    {
                        var key = line.Substring(0, line.IndexOf("=", StringComparison.Ordinal)).Trim();
                        var value = line.Substring(key.Length + 1);

                        if (currentSection == null)
                        {
                            currentSection = new ZSWF_IniSection();
                            sections.Add(currentSection.Title, currentSection);
                        }

                        if (!currentSection.ValueDict.ContainsKey(key))
                        {
                            currentSection.ValueDict.Add(key, value);
                        }
                    }
                }
            }
            return sections;
        }

        /// <summary>
        /// 通过路径解析配置文件（Hashtable）
        /// </summary>
        /// <param name="path"></param>
        /// <param name="encoding">编码格式</param>
        /// <returns></returns>
        public static Dictionary<string, Hashtable> GetIniContent(string path, Encoding encoding)
        {
            return ConvertToHashTableDict(ParseIni(path, encoding));
        }

        public static Dictionary<string, Hashtable> ConvertToHashTableDict(Dictionary<string, ZSWF_IniSection> iniDict)
        {
            Dictionary<string, Hashtable> contentDict = new Dictionary<string, Hashtable>();
            foreach (var kvp in iniDict)
            {
                contentDict.Add(kvp.Key, kvp.Value.ToHashTable());
            }
            return contentDict;
        }

        public static Dictionary<string, Hashtable> GetIniContent(string path)
        {
            return GetIniContent(path, Encoding.ASCII);
        }

        /// <summary>
        /// 通过指定流中解析配置文件
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="encoding">编码格式</param>
        /// <returns></returns>
        public static Dictionary<string, ZSWF_IniSection> ParseIni(Stream stream, Encoding encoding)
        {
            var sections = new Dictionary<string, ZSWF_IniSection>();
            using (StreamReader streamReader = new StreamReader(stream, encoding))
            {
                return ParseIni(streamReader.ReadToEnd());
            }
        }

        /// <summary>
        /// 通过路径解析配置文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="encoding">编码格式</param>
        /// <returns></returns>
        public static Dictionary<string, ZSWF_IniSection> ParseIni(string path, Encoding encoding)
        {
            return ParseIni(readFromFile(path, encoding));
        }

        /// <summary>
        /// 从目录中读取文本
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private static string readFromFile(string path, Encoding encoding)
        {
            FileStream fs = null;
            try
            {
                using (fs = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    if (Equals(encoding, Encoding.ASCII))
                    {
                        using (StreamReader sr = new StreamReader(fs, Encoding.UTF8))
                        {
                            return sr.ReadToEnd();
                        }
                    }
                    else
                    {
                        using (StreamReader sr = new StreamReader(fs, encoding))
                        {
                            return sr.ReadToEnd();
                        }
                    }
                }
            }
            catch (Exception)
            {
                fs?.Close();
                return "";
            }
        }
    }

    public class ZSWF_IniSection
    {
        private string m_title;
        private Dictionary<string, string> m_valueDict;
        public string Title => m_title;
        public Dictionary<string, string> ValueDict => m_valueDict;

        public ZSWF_IniSection(string title = null)
        {
            m_title = title;
            m_valueDict = new Dictionary<string, string>();
        }

        public ZSWF_IniSection(string title, Dictionary<string, string> dictionary)
        {
            m_title = title;
            m_valueDict = dictionary;
        }

        public Hashtable ToHashTable()
        {
            Hashtable hashtable = new Hashtable();
            foreach (var kvp in ValueDict)
            {
                hashtable.Add(kvp.Key, kvp.Value);
            }
            return hashtable;
        }
    }

    /// <summary>
    /// Ini配置文件读写助手
    /// </summary>
    public class ZSWF_IniHelper
    {
        private string m_path;
        private Encoding m_encoding = Encoding.UTF8;
        private Dictionary<string, ZSWF_IniSection> m_sectionDict;
        public Dictionary<string, ZSWF_IniSection> SectionDict => m_sectionDict;

        /// <summary>
        /// 通过目录解析配置文件
        /// </summary>
        /// <param name="path">保存路径</param>
        public ZSWF_IniHelper(string path)
        {
            m_sectionDict = ZSWF_Ini.ParseIni(path, m_encoding);
            m_path = path;
        }

        /// <summary>
        /// 通过字符串内容解析配置文件
        /// </summary>
        /// <param name="iniString">指定路径</param>
        /// <param name="savePath">可选保存路径</param>
        public ZSWF_IniHelper(string iniString, string savePath = null)
        {
            m_sectionDict = ZSWF_Ini.ParseIni(iniString);
            if (savePath != null)
            {
                m_path = savePath;
            }
        }

        /// <summary>
        /// 通过流解析配置文件
        /// </summary>
        /// <param name="stream">指定路径</param>
        /// <param name="savePath">可选保存路径</param>
        public ZSWF_IniHelper(Stream stream, string savePath = null)
        {
            using (StreamReader sr = new StreamReader(stream, m_encoding))
            {
                m_sectionDict = ZSWF_Ini.ParseIni(sr.ReadToEnd());
                if (savePath != null)
                {
                    m_path = savePath;
                }
            }
        }

        /// <summary>
        /// 查询配置文件key
        /// </summary>
        /// <param name="sectionName"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetValue(string sectionName, string key)
        {
            if (m_sectionDict.TryGetValue(sectionName, out ZSWF_IniSection section))
            {
                if (section.ValueDict.TryGetValue(key, out string value))
                {
                    return value;
                }
            }
            return null;
        }

        /// <summary>
        /// 查询配置文件节点
        /// </summary>
        /// <param name="sectionName"></param>
        /// <returns></returns>
        public ZSWF_IniSection GetSection(string sectionName)
        {
            if (m_sectionDict.TryGetValue(sectionName, out ZSWF_IniSection value))
            {
                return value;
            }
            return null;
        }

        public Hashtable GetSectionHashtable(string sectionName)
        {
            if (m_sectionDict.TryGetValue(sectionName, out ZSWF_IniSection value))
            {
                return value.ToHashTable();
            }
            return null;
        }

        public Dictionary<string, Hashtable> GetAllContent()
        {
            return ZSWF_Ini.ConvertToHashTableDict(m_sectionDict);
        }

        /// <summary>
        /// 设置配置文件参数,若不存在则创建
        /// </summary>
        /// <param name="sectionName"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="isSave"></param>
        /// <returns></returns>
        public bool SetValue(string sectionName, string key, string value, bool isSave = true)
        {
            if (m_sectionDict.TryGetValue(sectionName, out ZSWF_IniSection sectionValue))
            {
                if (sectionValue.ValueDict.ContainsKey(key))
                {
                    sectionValue.ValueDict[key] = value;
                }
                else
                {
                    sectionValue.ValueDict.Add(key, value);
                }
            }
            else
            {
                ZSWF_IniSection section = new ZSWF_IniSection(sectionName);
                section.ValueDict.Add(key, value);
                m_sectionDict.Add(section.Title, section);
            }

            if (isSave)
            {
                Save(m_path);
            }

            return true;
        }

        /// <summary>
        /// 保存配置到文件,Webgl不支持
        /// </summary>
        public void Save(string path)
        {
            if (path == null || Application.platform == RuntimePlatform.WebGLPlayer)
            {
                return;
            }
            writeInFile(path, this.ToString());
        }

        public void Save()
        {
            if (m_path != null)
            {
                Save(m_path);
            }
        }


        /// <summary>
        /// 转换为可写入文件的字符串格式
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            string content = "";
            if (m_sectionDict.Count == 0)
            {
                return content;
            }
            foreach (var section in m_sectionDict.Values)
            {
                if (section.Title == "")
                {
                    continue;
                }
                content += $"[{section.Title}]" + "\r\n";
                foreach (var kvp in section.ValueDict)
                {
                    content += $"{kvp.Key}={kvp.Value}" + "\r\n";
                }
                content += "\r\n";
            }
            return content;
        }



        /// <summary>
        /// 写入内容到文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="contents"></param>
        /// <returns></returns>
        private void writeInFile(string path, string contents)
        {
            FileStream fs = null;
            try
            {
                using (fs = new FileStream(path, FileMode.Create, FileAccess.Write))
                {
                    using (StreamWriter sw = new StreamWriter(fs, m_encoding))
                    {
                        sw.Write(contents);
                    }
                }
            }
            catch
            {
                fs?.Close();
            }
        }

        public void AddSession(string title, ZSWF_IniSection iniSection)
        {
            if (!m_sectionDict.ContainsKey(title))
            {
                m_sectionDict.Add(title, iniSection);
                Save();
            }
        }

        public void RemoveSession(string title)
        {
            m_sectionDict.Remove(title);
            Save();
        }
    }
}